function testCaseInfo = getModelTestCaseStatus(modelName)
% getModelTestCaseStatus 获取指定模型的测试用例信息
%
% 输入:
%   modelName - 模型名称（字符串）
%
% 输出:
%   testCaseInfo - 测试用例信息结构体数组，包含以下字段：
%       TestID       - 测试用例ID
%       Description  - 测试用例描述
%       Type         - 输入数据来源类型（Signal Editor/Test Sequence）
%       Status       - 测试状态（Passed/Failed/Incomplete/Disabled）
%       Requirement  - 关联的需求描述（带超链接）
%       StartTime    - 测试开始时间
%
% 示例:
%   testCaseInfo = getModelTestCaseStatus('MyModel');
%
% 遵循第2条规则：不建立fallback机制，所有错误明确报告

% Copyright 2025 MathWorks, Inc.

% 基于第2条规则：严禁使用fallback机制
% 如果结果文件不存在或信息无法获取，返回空数组

    % 初始化输出为空结构体数组
    testCaseInfo = struct('TestID', {}, 'Description', {}, 'Type', {}, ...
        'Status', {}, 'Requirement', {}, 'RequirementURL', {}, 'StartTime', {});

% 验证输入
if nargin < 1 || isempty(modelName)
    error('getModelTestCaseStatus:InvalidInput', '必须提供模型名称');
end

try
    % 构造结果文件路径
    resultFile = fullfile(ProjectPathManager.getDirPath('HLR sim results', modelName), ...
        [ProjectNamingManager.getNameStr('HLR sim results', modelName), '.mldatx']);

    % 检查结果文件是否存在
    if ~exist(resultFile, 'file')
        % 基于第2条规则：不使用fallback，返回空数组
        warning('getModelTestCaseStatus:ResultFileNotFound', ...
            '找不到结果文件: %s\n可能还未运行测试', resultFile);
        return;
    end

    % 导入结果文件
    resultSet = sltest.testmanager.importResults(resultFile);
    if isempty(resultSet)
        warning('getModelTestCaseStatus:EmptyResultSet', ...
            '无法导入结果文件: %s', resultFile);
        return;
    end

    % 获取测试文件结果
    fileResults = getTestFileResults(resultSet);

    % 遍历层级结构提取测试用例信息
    testCaseCount = 0;
    for f = 1:numel(fileResults)
        % 从测试文件结果中获取测试套件结果
        suiteResults = getTestSuiteResults(fileResults(f));

        for s = 1:numel(suiteResults)
            % 从测试套件结果中获取测试用例结果
            tcResults = getTestCaseResults(suiteResults(s));

            for i = 1:numel(tcResults)
                tcr = tcResults(i);
                testCaseCount = testCaseCount + 1;

                % 从 TestCaseResult 直接获取所有信息
                testCaseInfo(testCaseCount).TestID = getTestID(tcr);
                testCaseInfo(testCaseCount).Description = getDescription(tcr);
                testCaseInfo(testCaseCount).Type = getTestCaseType(tcr);
                testCaseInfo(testCaseCount).Status = getTestStatus(tcr);
                
                % 获取需求信息（描述和URL分开）
                [reqDesc, reqURL] = getRequirementInfo(tcr);
                testCaseInfo(testCaseCount).Requirement = reqDesc;
                testCaseInfo(testCaseCount).RequirementURL = reqURL;
                
                testCaseInfo(testCaseCount).StartTime = getStartTime(tcr);
            end
        end
    end

    % 如果没有找到任何测试用例
    if testCaseCount == 0
        warning('getModelTestCaseStatus:NoTestCases', ...
            '结果文件中没有测试用例: %s', resultFile);
    end

catch ME
    % 基于第2条规则：明确报告所有错误
    error('getModelTestCaseStatus:ExecutionError', ...
        '获取测试用例信息时发生错误: %s\n错误详情: %s', ...
        ME.message, getReport(ME));
end
end

%% 辅助函数

function testID = getTestID(tcr)
% 从 TestCaseResult 获取测试用例 ID
try
    if isprop(tcr, 'Name')
        testID = tcr.Name;
    else
        testID = '未知ID';
    end
catch
    testID = '未知ID';
end
end

function description = getDescription(tcr)
% 从 TestCaseResult 获取测试用例描述
try
    if isprop(tcr, 'Description') && ~isempty(tcr.Description)
        description = tcr.Description;
    else
        description = '无描述';
    end
catch
    description = '无法获取描述';
end
end

function testType = getTestCaseType(tcr)
% 从 TestCaseResult 获取测试用例的输入数据来源类型
% 检查 SignalBuilderGroup 和 TestSequenceScenario

try
    % 检查 Signal Editor (SignalBuilderGroup)
    % 这里判断tcr.SignalBuilderGroup结构体是否有SignalBuilderGroup字段或者SignalEditorBlock字段
    if isstruct(tcr.SignalBuilderGroup)
        if isfield(tcr.SignalBuilderGroup, 'SignalBuilderGroup') && ~isempty(tcr.SignalBuilderGroup.SignalBuilderGroup)
            testType = 'Signal Editor';
            return;
        elseif isfield(tcr.SignalBuilderGroup, 'SignalEditorBlock') && ~isempty(tcr.SignalBuilderGroup.SignalEditorBlock)
            testType = 'Signal Editor';
            return;
        end
    end

    % 检查 Test Sequence (TestSequenceScenario)
    if isstruct(tcr.TestSequenceScenario)
        % 进一步检查是否有 Name 属性
        if isfield(tcr.TestSequenceScenario,"TestSequenceScenario") && ~isempty(tcr.TestSequenceScenario.TestSequenceScenario)
            testType = 'Test Sequence';
            return;
        end
    end

    % 如果都没有，返回未知类型
    testType = 'Test Sequence';

catch ME
    % 基于第2条规则：明确报告错误
    warning('getModelTestCaseStatus:CannotGetInputType', ...
        '无法获取测试用例 %s 的输入类型: %s', tcr.Name, ME.message);
    testType = '无法获取类型';
end
end

function status = getTestStatus(tcr)
% 从 TestCaseResult 获取测试状态
try
    if isprop(tcr, 'Outcome')
        outcome = tcr.Outcome;
        if isnumeric(outcome)
            switch outcome
                case 0, status = 'Disabled';
                case 1, status = 'Incomplete';
                case 2, status = 'Passed';
                case 3, status = 'Failed';
                otherwise, status = '未知状态';
            end
        elseif ischar(outcome) || isstring(outcome)
            status = char(outcome);
        else
            status = '未知状态';
        end
    else
        status = '未知状态';
    end
catch
    status = '未知状态';
end
end

function startTime = getStartTime(tcr)
% 从 TestCaseResult 获取测试开始时间
try
    if isprop(tcr, 'StartTime') && ~isempty(tcr.StartTime)
        % 转换为字符串格式
        startTime = char(string(tcr.StartTime));
    else
        startTime = '未知时间';
    end
catch
    startTime = '未知时间';
end
end


function [reqDesc, reqURL] = getRequirementInfo(tcr)
% 从 TestCaseResult 获取需求信息（描述和URL分开）
% 从 tcr.Requirements 结构体获取 description 和 docurl
%
% 输出:
%   reqDesc - 需求描述字符串（用于表格显示）
%   reqURL - 需求URL字符串（用于点击打开）

reqDesc = '';
reqURL = '';

try
    if ~isprop(tcr, 'Requirements') || isempty(tcr.Requirements)
        reqDesc = '无关联需求';
        reqURL = '';
        return;
    end

    reqDescList = {};
    reqURLList = {};
    reqs = tcr.Requirements;

    for i = 1:numel(reqs)
        req = reqs(i);
        
        % 获取需求描述
        currentDesc = '';
        if isfield(req, 'description') && ~isempty(req.description)
            currentDesc = char(string(req.description));
        elseif isfield(req, 'Description') && ~isempty(req.Description)
            currentDesc = char(string(req.Description));
        elseif isfield(req, 'summary') && ~isempty(req.summary)
            currentDesc = char(string(req.summary));
        elseif isfield(req, 'Summary') && ~isempty(req.Summary)
            currentDesc = char(string(req.Summary));
        else
            currentDesc = '需求描述未知';
        end

        % 获取需求链接
        currentURL = '';
        if isfield(req, 'docurl') && ~isempty(req.docurl)
            currentURL = char(string(req.docurl));
        elseif isfield(req, 'Docurl') && ~isempty(req.Docurl)
            currentURL = char(string(req.Docurl));
        elseif isfield(req, 'url') && ~isempty(req.url)
            currentURL = char(string(req.url));
        elseif isfield(req, 'Url') && ~isempty(req.Url)
            currentURL = char(string(req.Url));
        end
        
        % 添加到列表
        reqDescList{end+1} = currentDesc; %#ok<AGROW>
        reqURLList{end+1} = currentURL; %#ok<AGROW>
    end

    % 合并多个需求
    if ~isempty(reqDescList)
        reqDesc = strjoin(reqDescList, '; ');
        reqURL = strjoin(reqURLList, ';'); % 使用分号分隔多个URL
    else
        reqDesc = '无关联需求';
        reqURL = '';
    end

catch ME
    % 基于第2条规则：明确报告错误
    warning('getModelTestCaseStatus:CannotGetRequirements', ...
        '无法获取测试用例 %s 的需求信息: %s', tcr.Name, ME.message);
    reqDesc = '无法获取需求';
    reqURL = '';
end
end

